package dialer.ws.common.util;

import java.io.InputStream;
import java.util.List;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.faces.FactoryFinder;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.faces.model.SelectItem;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * @author ediaz
 * 
 */
public class FacesUtils {

	public static FacesContext getFacesContext() {
		return FacesContext.getCurrentInstance();
	}

	public static ServletContext getServletContext() {
		return (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
	}

	public static ExternalContext getExternalContext() {
		return (ExternalContext) FacesContext.getCurrentInstance().getExternalContext();
	}

	public static String getLabel(List<SelectItem> list, Object value) {
		for (SelectItem si : list) {
			if (si.getValue().equals(value)) {
				return si.getLabel();
			}
		}
		return null;
	}

	public static InputStream getStream(String path) {
		return getExternalContext().getResourceAsStream(path);
	}

	/**
	 * Get parameter value from request scope.
	 * 
	 * @param name
	 *            the name of the parameter
	 * @return the parameter value
	 */
	public static String getRequestParameter(String name) {
		return (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(name);
	}

	/**
	 * Add information message.
	 * 
	 * @param msg
	 *            the information message
	 */
	public static void addInfoMessage(String title, String msg) {
		addInfoMessage(null, title, msg);
	}

	/**
	 * Add information message to a sepcific client.
	 * 
	 * @param clientId
	 *            the client id
	 * @param msg
	 *            the information message
	 */
	public static void addInfoMessage(String clientId, String title, String msg) {
		FacesContext.getCurrentInstance()
				.addMessage(clientId, new FacesMessage(FacesMessage.SEVERITY_INFO, title, msg));
	}

	/**
	 * Add error message.
	 * 
	 * @param msg
	 *            the error message
	 */
	public static void addErrorMessage(String title, String msg) {
		addErrorMessage(null, title, msg);
	}

	/**
	 * Add error message to a sepcific client.
	 * 
	 * @param clientId
	 *            the client id
	 * @param msg
	 *            the error message
	 */
	public static void addErrorMessage(String clientId, String title, String msg) {
		FacesContext.getCurrentInstance().addMessage(clientId,
				new FacesMessage(FacesMessage.SEVERITY_ERROR, title, msg));
	}

	public static void addWarnMessage(String title, String msg) {
		addWarnMessage(null, title, msg);
	}

	public static void addWarnMessage(String clientId, String title, String msg) {
		FacesContext.getCurrentInstance()
				.addMessage(clientId, new FacesMessage(FacesMessage.SEVERITY_WARN, title, msg));
	}

	public static HttpServletRequest getRequest() {
		return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
	}

	public static HttpServletResponse getResponse() {
		return (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
	}

	public static HttpSession getSession() {
		return (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
	}

	public static Object getManagedBean(FacesContext ctx, String beanName) {
		Object bean = ctx.getApplication().getELResolver().getValue(ctx.getELContext(), null, beanName);
		return bean;
	}

	public static Object getManagedBean(String beanName) {
		return getManagedBean(FacesContext.getCurrentInstance(), beanName);
	}

	public static MethodExpression createMethodExpression(String action, Class<?> returnType, Class[] attributes) {
		ExpressionFactory ef = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
		ELContext elContext = FacesContext.getCurrentInstance().getELContext();
		MethodExpression me = ef.createMethodExpression(elContext, action, returnType, attributes);
		return me;
	}

	public static Object invoke(MethodExpression mex, Object[] args) {
		ELContext elContext = FacesContext.getCurrentInstance().getELContext();
		return mex.invoke(elContext, args);
	}

	public static Object getSpringBean(String beanName) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		ExternalContext externalContext = facesContext.getExternalContext();
		ServletContext svCtx = (ServletContext) (externalContext.getContext());
		return WebApplicationContextUtils.getWebApplicationContext(svCtx).getBean(beanName);
	}

	public static FacesContext getFacesContext(ServletContext servletContext, ServletRequest request,
			ServletResponse response) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		if (facesContext != null)
			return facesContext;

		FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder
				.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
		LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
				.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
		Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
		facesContext = contextFactory.getFacesContext(servletContext, request, response, lifecycle);
		return facesContext;
	}

}
